package com.coldworks.base.task;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;

import android.net.Uri;

import android.os.AsyncTask;

import com.coldworks.base.manager.BaseNetworkManager;
import com.coldworks.base.util.BaseCONST;
import com.coldworks.coldjoke.R;

/**
 * apk文件同步下载类
 * 
 * @since 2012-03-23
 */
public class BaseApkDownloadTask extends AsyncTask<Void, Integer, Integer> {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	private Context ctx; // 主UI线程上下文
	private String downloadURL; // 下载地址
	private String localFileStr; // 本地保存地址
	private boolean installAfterDownload; // 是否下载完后直接进行安装
	private boolean askForInstall; // 是否询问用户安装还是下载完后直接安装
	private boolean existBeforeInstall; // 安装前是否先退出应用程序

	private ProgressDialog downPrg; // 下载进度条
	private int count; // 版本更新下载进度 - 当前值
	private int total; // 版本更新下载进度 - 总值

	public BaseApkDownloadTask(Context ctx, String downloadURL,
			String localFileStr, boolean installAfterDownload,
			boolean askForInstall, boolean existBeforeInstall) {
		this.ctx = ctx;
		this.downloadURL = downloadURL;
		this.localFileStr = localFileStr;
		this.installAfterDownload = installAfterDownload;
		this.askForInstall = askForInstall;
		this.existBeforeInstall = existBeforeInstall;
		this.count = 0;
		this.total = -1;
		log.info("" + downloadURL + " " + localFileStr + " "
				+ installAfterDownload + " " + askForInstall + " "
				+ existBeforeInstall);
	}

	@Override
	protected void onPreExecute() {
		this.downPrg = new ProgressDialog(this.ctx);
		this.downPrg.setIndeterminate(false);
		this.downPrg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		this.downPrg.setMessage(this.ctx.getString(R.string.connecting));
		this.downPrg.setCancelable(false);
		this.downPrg.show();
	}

	@Override
	protected Integer doInBackground(Void... params) {
		log.info("start downloading");
		File file = new File(this.localFileStr);
		if (file.exists()) {
			file.delete();
		}
		try {
			file.createNewFile();
		} catch (IOException e) {
			log.error("", e);
			return BaseCONST.OP.ERR_IO;
		}
		InputStream is = null;
		FileOutputStream fos = null;
		try {
			HttpEntity entity = BaseNetworkManager.getInstance().httpGETEntity(
					ctx, this.downloadURL);
			int size = (int) entity.getContentLength();
			this.publishProgress(size);
			is = entity.getContent();
			if (is == null) {
				return BaseCONST.OP.ERR_NET;
			}
			fos = new FileOutputStream(file);
			byte[] buf = new byte[BaseCONST.HTTP.BUFFER_SIZE];
			int ch = -1;
			while ((ch = is.read(buf)) != -1) {
				if (isCancelled()) {
					throw new InterruptedException();
				}
				this.count += ch;
				fos.write(buf, 0, ch);
				this.publishProgress(this.count);
			}
			fos.flush();
			if (fos != null)
				fos.close();
			if (this.count == size) {
				return BaseCONST.OP.SUCC;
			} else {
				return BaseCONST.OP.ERR_IO;
			}
		} catch (IOException e) {
			log.error("", e);
			return BaseCONST.OP.ERR_IO;
		} catch (InterruptedException e) {
			log.error("", e);
			return BaseCONST.OP.CANCEL;
		} catch (Exception e) {
			log.error("", e);
			return BaseCONST.OP.ERR_NET;
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				log.error("", e);
			}
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				log.error("", e);
			}
		}
	}

	@Override
	protected void onProgressUpdate(Integer... progress) {
		if (this.total == -1) {
			this.total = progress[0];
			this.downPrg.setMessage(this.ctx.getString(R.string.downloading));
			this.downPrg.setCancelable(true);
			this.downPrg.setButton(this.ctx.getString(R.string.cancel),
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							BaseApkDownloadTask.this.cancel(true);
						}
					});
			this.downPrg.setMax(this.total);
			this.downPrg.setProgress(0);
			log.info("progress bar begin");
		} else if (this.downPrg != null) {
			this.downPrg.setProgress(progress[0]);
		}
	}

	@Override
	protected void onPostExecute(Integer result) {
		if (this.downPrg != null) {
			this.downPrg.dismiss();
		}
		switch (result) {
		case BaseCONST.OP.SUCC:
			log.info("progress bar finish");
			if (this.installAfterDownload) {
				if (this.askForInstall) {
					new AlertDialog.Builder(this.ctx)
							.setTitle(R.string.tips)
							.setCancelable(false)
							.setMessage(
									this.ctx.getString(R.string.install_confirm))
							.setPositiveButton(
									this.ctx.getString(R.string.yes),
									new DialogInterface.OnClickListener() {
										public void onClick(
												DialogInterface dialog,
												int which) {
											dialog.dismiss();
											BaseApkDownloadTask.this.install();
										}
									})
							.setNegativeButton(this.ctx.getString(R.string.no),
									new DialogInterface.OnClickListener() {
										public void onClick(
												DialogInterface dialog,
												int which) {
											dialog.dismiss();
										}
									}).show();
				} else {
					BaseApkDownloadTask.this.install();
				}
			}
			break;
		// 下载遇到IO异常
		case BaseCONST.OP.ERR_IO:
			log.info("stop by io err");
			new AlertDialog.Builder(this.ctx)
					.setTitle(R.string.tips)
					.setCancelable(false)
					.setMessage(this.ctx.getString(R.string.err_bad_file))
					.setPositiveButton(this.ctx.getString(R.string.back),
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							}).show();
			// 下载遇到网络异常
			break;
		case BaseCONST.OP.ERR_NET:
			log.info("stop by network err");
			new AlertDialog.Builder(this.ctx)
					.setTitle(R.string.tips)
					.setCancelable(false)
					.setMessage(this.ctx.getString(R.string.err_connecting))
					.setPositiveButton(this.ctx.getString(R.string.back),
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							}).show();
			break;
		// 下载被用户中断
		case BaseCONST.OP.CANCEL:
			log.info("stop by cancel");
			break;
		}
	}

	/*
	 * 如果已经下载新版文件则调用此方法进行安裝
	 */
	private void install() {
		Intent i = new Intent();
		i.setAction(Intent.ACTION_VIEW);
		i.setDataAndType(Uri.fromFile(new File(this.localFileStr)),
				BaseCONST.API.INSTALL_CMD);
		this.ctx.startActivity(i);
		if (this.existBeforeInstall) {
			this.downPrg.cancel();
			((Activity) this.ctx).finish();
		}
		log.info("start installing");
	}

}